/*
 * Copyright (C) 2018 Logos Technology Ltd.
 */

package com.logos.tool.image;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.media.MediaScannerConnection;
import android.net.Uri;

import androidx.annotation.Nullable;

import com.logos.tool.TimeUtil;
import com.logos.tool.file.StorageUtils;
import com.logos.tool.string.StringUtil;
import com.zxy.tiny.Tiny;
import com.zxy.tiny.callback.FileCallback;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * @author Young Ken
 */

public class PicUtil {

    /**
     * 读取图片属性：旋转的角度
     *
     * @param path 图片绝对路径
     * @return degree旋转的角度
     */
    public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
                default:
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 读取图片属性：旋转的角度
     *
     * @param inputStream inputStream
     * @return degree旋转的角度
     */
    public static int readPictureDegree(InputStream inputStream) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(inputStream);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
                default:
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 旋转图片
     *
     * @param angle  int
     * @param bitmap bitmap
     * @return Bitmap
     */
    public static Bitmap rotatingImageView(int angle, @Nullable Bitmap bitmap) {
        if (angle == 0) {
            return bitmap;
        }
        //旋转图片 动作
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        // 创建新的图片
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
                bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return resizedBitmap;
    }

    /**
     * file CallBack
     */
    public interface FileCallBack {

        /**
         * success
         *
         * @param filePath filePath
         */
        void onSuccess(String filePath);
    }

    /**
     * save bitmap 2 file
     *
     * @param context  context
     * @param bitmap   Bitmap
     * @param path     path
     * @param callBack FileCallBack
     */
    public static void saveBitmap2File(final Context context, Bitmap bitmap, String path,
                                       final FileCallBack callBack) {
        String filePath = StorageUtils.getStorage().getAbsolutePath() + path;//照片保存路径
        String fileName = System.currentTimeMillis() + ".jpg";//照片保存路径
        File dir = new File(filePath);
        if (!dir.exists() && !dir.isDirectory()) {
            //判断文件目录是否存在
            dir.mkdirs();
        }
        String outfile = filePath + fileName;
        save(bitmap, new File(outfile), Bitmap.CompressFormat.JPEG, false);
        if (callBack != null) {
            callBack.onSuccess(outfile);
            MediaScannerConnection.scanFile(context.getApplicationContext(),
                    new String[]{outfile}, null, null);
        }
    }

    /**
     * 增加方法，图片路径为yyyyMMddHHmmss
     * save bitmap 2 file
     *
     * @param context  context
     * @param bitmap   Bitmap
     * @param path     path
     * @param callBack FileCallBack
     */
    public static void saveBitmapToFile(final Context context, Bitmap bitmap, String path,
                                        final FileCallBack callBack) {
        String filePath = StorageUtils.getStorage().getAbsolutePath() + path;//照片保存路径
        String fileName = TimeUtil.timeStamp2Date(System.currentTimeMillis(), "yyyyMMddHHmmssSSS") + ".jpg";//照片保存路径
        File dir = new File(filePath);
        if (!dir.exists() && !dir.isDirectory()) {
            //判断文件目录是否存在
            dir.mkdirs();
        }
        String outfile = filePath + fileName;
        save(bitmap, new File(outfile), Bitmap.CompressFormat.JPEG, false);
        if (callBack != null) {
            callBack.onSuccess(outfile);
            MediaScannerConnection.scanFile(context.getApplicationContext(),
                    new String[]{outfile}, null, null);
        }
    }

    /**
     * save byte 2 file
     *
     * @param context  context
     * @param data     data
     * @param path     path
     * @param callBack callBack
     */
    public static void saveByte2File(final Context context, byte[] data, String path,
                                     final FileCallBack callBack) {
        String filePath = StorageUtils.getStorage().getAbsolutePath() + path;//照片保存路径
        String fileName = System.currentTimeMillis() + ".jpg";//照片保存路径
        File dir = new File(filePath);
        if (!dir.exists() && !dir.isDirectory()) {
            //判断文件目录是否存在
            dir.mkdirs();
        }
        Tiny.FileCompressOptions options = new Tiny.FileCompressOptions();
        options.outfile = filePath + fileName;
        options.width = 1200;
        options.height = 1600;
        options.quality = 70;
        Tiny.getInstance().source(data).asFile().withOptions(options).compress(new FileCallback() {
            @Override
            public void callback(boolean isSuccess, String outfile, Throwable throwable) {
                if (callBack != null) {
                    callBack.onSuccess(outfile);
                    MediaScannerConnection.scanFile(context.getApplicationContext(),
                            new String[]{outfile}, null, null);
                }
            }
        });
    }

    /**
     * Save the bitmap.
     *
     * @param src     The source of bitmap.
     * @param file    The file.
     * @param format  The format of the image.
     * @param recycle True to recycle the source of bitmap, false otherwise.
     * @return {@code true}: success<br>{@code false}: fail
     */
    public static boolean save(final Bitmap src,
                               final File file,
                               final Bitmap.CompressFormat format,
                               final boolean recycle) {
        if (isEmptyBitmap(src) || !createFileByDeleteOldFile(file)) {
            return false;
        }
        OutputStream os = null;
        boolean ret = false;
        try {
            os = new BufferedOutputStream(new FileOutputStream(file));
            ret = src.compress(format, 100, os);
            if (recycle && !src.isRecycled()) {
                src.recycle();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ret;
    }

    private static boolean isEmptyBitmap(final Bitmap src) {
        return src == null || src.getWidth() == 0 || src.getHeight() == 0;
    }

    private static boolean createFileByDeleteOldFile(final File file) {
        if (file == null) {
            return false;
        }
        if (file.exists() && !file.delete()) {
            return false;
        }
        if (!createOrExistsDir(file.getParentFile())) {
            return false;
        }
        try {
            return file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    private static boolean createOrExistsDir(final File file) {
        return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
    }

    private static Bitmap loadLocalFiles(String imagePath) {

        FileInputStream fis = null;
        Bitmap result = null;
        try {
            fis = new FileInputStream(imagePath);
            result = BitmapFactory.decodeStream(fis);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * saveImageToGallery
     *
     * @param context  context
     * @param bmp      Bitmap
     * @param path     String
     * @param fileName String
     * @return file
     */
    public static File saveImageToGallery(Context context, Bitmap bmp,
                                          String path, String fileName) {
        String filePath = StorageUtils.getStorage().getAbsolutePath()
                + path;//照片保存路径
        File dir = new File(filePath);
        if (!dir.exists() && !dir.isDirectory()) {
            //判断文件目录是否存在
            dir.mkdirs();
        }
        if (StringUtil.isEmpty(fileName)) {
            fileName = System.currentTimeMillis() + ".jpg";//照片保存路径
        }
        File currentFile = new File(filePath, fileName);

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(currentFile);
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 最后通知图库更新
        context.getApplicationContext()
                .sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                        Uri.fromFile(new File(currentFile.getAbsolutePath()))));

        return currentFile;
    }

    /**
     * 获取Png格式的签名图片文件
     *
     * @param context   context
     * @param signature signature
     * @return file
     */
    public static File addPngSignatureToGallery(Context context, Bitmap signature) {
        try {
            String signaturePad = StorageUtils.getCacheDirectory(context, "SignaturePad")
                    .getAbsolutePath();
            File photo = new File(signaturePad,
                    String.format("Signature_%d.png", System.currentTimeMillis()));
            saveBitmapToPng(signature, photo);
            // 最后通知图库更新
            context.getApplicationContext()
                    .sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                            Uri.fromFile(new File(photo.getAbsolutePath()))));
            return photo;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static void saveBitmapToPng(Bitmap bitmap, File photo) throws IOException {
        Bitmap newBitmap = Bitmap
                .createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(newBitmap);
        canvas.drawColor(Color.TRANSPARENT);
        canvas.drawBitmap(bitmap, 0, 0, null);
        OutputStream stream = new FileOutputStream(photo);
        newBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
        stream.close();
    }

    /**
     * 获取路径下的所有图片
     *
     * @param strPath 路径
     * @return 图片路径集合
     */
    public static List<String> getPictures(final String strPath) {
        List<String> list = new ArrayList<>();
        File file = new File(strPath);
        File[] allfiles = file.listFiles();
        if (allfiles == null) {
            return list;
        }
        Arrays.sort(allfiles, new ComparatorByLastModified());
        for (int i = 0; i < allfiles.length; i++) {
            final File fi = allfiles[i];
            if (fi.isFile()) {
                int idx = fi.getPath().lastIndexOf(".");
                if (idx <= 0) {
                    continue;
                }
                String suffix = fi.getPath().substring(idx);
                if (suffix.toLowerCase().equals(".jpg")
                        || suffix.toLowerCase().equals(".jpeg")
                        || suffix.toLowerCase().equals(".bmp")
                        || suffix.toLowerCase().equals(".png")
                        || suffix.toLowerCase().equals(".gif")) {
                    list.add(fi.getPath());
                }
            }
        }
        return list;
    }

    static class ComparatorByLastModified implements Comparator<File> {
        public int compare(File f1, File f2) {
            long diff = f1.lastModified() - f2.lastModified();
            if (diff > 0) {
                return -1;
            } else if (diff == 0) {
                return 0;
            } else {
                return 1;
            }
        }

        public boolean equals(Object obj) {
            return true;
        }
    }

}

